package org.aplikator.client.widgets;

import java.io.Serializable;
import java.util.List;

import org.aplikator.client.Aplikator;
import org.aplikator.client.command.MainPanelTitleCallback;
import org.aplikator.client.data.Operation;
import org.aplikator.client.data.PrimaryKey;
import org.aplikator.client.data.RecordContainer;
import org.aplikator.client.data.Record;
import org.aplikator.client.descriptor.ViewDTO;
import org.aplikator.client.descriptor.PropertyDTO;
import org.aplikator.client.panels.HorizontalFlowPanel;
import org.aplikator.client.rpc.Callback;
import org.aplikator.client.rpc.impl.GetPage;
import org.aplikator.client.rpc.impl.GetPageResponse;
import org.aplikator.client.rpc.impl.GetRecord;
import org.aplikator.client.rpc.impl.GetRecordCount;
import org.aplikator.client.rpc.impl.GetRecordCountResponse;
import org.aplikator.client.rpc.impl.GetRecordResponse;
import org.aplikator.client.rpc.impl.ProcessRecords;
import org.aplikator.client.rpc.impl.ProcessRecordsResponse;

import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.i18n.client.LocaleInfo;
import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.resources.client.CssResource;
import com.google.gwt.resources.client.ImageResource;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.DialogBox;
import com.google.gwt.user.client.ui.DockLayoutPanel;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.FlexTable.FlexCellFormatter;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HTMLTable.Cell;
import com.google.gwt.user.client.ui.HTMLTable.RowFormatter;
import com.google.gwt.user.client.ui.HasAlignment;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.InlineHTML;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.ToggleButton;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;

public class TableWidget extends Composite implements TableInterface {

    public interface TableWidgetResources extends ClientBundle {
        public static final TableWidgetResources INSTANCE = GWT.create(TableWidgetResources.class);

        @Source("images/icons/first16.png")
        ImageResource first();

        @Source("images/icons/prev16.png")
        ImageResource prev();

        @Source("images/icons/next16.png")
        ImageResource next();

        @Source("images/icons/last16.png")
        ImageResource last();

        @Source("images/icons/create16.png")
        ImageResource create();

        @Source("images/icons/open16.png")
        ImageResource open();

        @Source("images/icons/delete16.png")
        ImageResource delete();

        @Source("images/icons/copy16.png")
        ImageResource copy();

        @Source("images/icons/reload16.png")
        ImageResource reload();

        @Source("images/icons/find16.png")
        ImageResource find();

        @Source("images/icons/cancel16.png")
        ImageResource cancel();

        @Source("images/icons/save16.png")
        ImageResource save();

        @Source("images/icons/arrowUp16.png")
        ImageResource arrowUp();

        @Source("images/icons/arrowDown16.png")
        ImageResource arrowDown();

        @Source("images/icons/zoomin16.png")
        ImageResource zoomIn();

        @Source("images/icons/zoomout16.png")
        ImageResource zoomOut();

        @Source("TableWidget.css")
        public TableWidgetCss css();
    }

    public interface TableWidgetCss extends CssResource {
        public String tableBody();

        public String tableColumn();

        public String tableHeader();

        public String tableHeaderCell();

        public String tableOddRow();

        public String tableEvenRow();

        public String tableSelectedRow();

        public String tableHoveredRow();

        public String tableNavigationPanel();

        public String toolbarButton();
    }

    static {
        TableWidgetResources.INSTANCE.css().ensureInjected();
    }

    private static final String EMPTY_CELL = "&nbsp;";

    private static final int DOUBLECLICK_TRESHOLD = 500;

    private static final int HEADER_ROWS = 2;

    private static final int LEADING_COLUMNS = 3;

    // private static final int TRAILING_COLUMNS = 1;

    private final SimplePanel dataPanel;

    private final HorizontalFlowPanel navigationPanel;
    private final InlineHTML statusLabel;
    private final Label searchID;
    private final Image buttonFirstPage;
    private final Image buttonPrevPage;
    private final Image buttonNextPage;
    private final Image buttonLastPage;
    private final TextBox searchField;
    private final Image buttonSearch;
    private Image buttonCreate;
    private Image buttonOpen;
    private Image buttonDelete;
    private final Image buttonCopy;
    private final Image buttonReload;
    private final Image buttonClose;
    private final Image buttonSave;

    private final FlexTable grid;

    private final FlexCellFormatter gridFormatter;

    private FormWidget form;

    private boolean gridMode;

    private MainPanelTitleCallback titleCallback;
    private ViewDTO view;
    private List<Record> pageData;
    private int pageOffset = 0;
    private int pageSize = 0;
    private int selectedRow = 0;
    private int recordCount = 0;

    private PrimaryKey ownerPrimaryKey;

    private PropertyDTO<Integer> ownerProperty;

    private FormWidget ownerForm;

    RecordContainer recordContainer;

    private long lastClickTime = 0;
    private int lastClickRow = 0;

    public TableWidget(ViewDTO view, PropertyDTO<Integer> ownerProperty, FormWidget ownerForm) {
        super();
        this.view = view;
        this.pageSize = view.getPageSize();
        this.ownerProperty = ownerProperty;
        this.ownerForm = ownerForm;
        final DockLayoutPanel basePanel = new DockLayoutPanel(Unit.EM);
        // basePanel.getElement().getStyle().setPosition(Position.RELATIVE);
        initWidget(basePanel);
        // Top navigation panel
        navigationPanel = new HorizontalFlowPanel();
        navigationPanel.setVerticalAlignment(HasAlignment.ALIGN_MIDDLE);
        // navigationPanel.setWidth("100%");

        // navigationPanel.getElement().getStyle().setPosition(Position.RELATIVE);

        basePanel.addNorth(navigationPanel, 2);
        // paging buttons
        buttonFirstPage = new Image(TableWidgetResources.INSTANCE.first());
        buttonFirstPage.setStyleName(TableWidgetResources.INSTANCE.css().toolbarButton());
        navigationPanel.add(buttonFirstPage);
        buttonFirstPage.addClickHandler(new ClickHandler() {
            public void onClick(ClickEvent event) {
                TableWidget.this.buttonFirstPageClicked();
            }
        });

        buttonPrevPage = new Image(TableWidgetResources.INSTANCE.prev());
        buttonPrevPage.setStyleName(TableWidgetResources.INSTANCE.css().toolbarButton());
        navigationPanel.add(buttonPrevPage);
        buttonPrevPage.addClickHandler(new ClickHandler() {
            public void onClick(ClickEvent event) {
                TableWidget.this.buttonPrevPageClicked();
            }
        });

        buttonNextPage = new Image(TableWidgetResources.INSTANCE.next());
        buttonNextPage.setStyleName(TableWidgetResources.INSTANCE.css().toolbarButton());
        navigationPanel.add(buttonNextPage);
        buttonNextPage.addClickHandler(new ClickHandler() {
            public void onClick(ClickEvent event) {
                TableWidget.this.buttonNextPageClicked();
            }
        });

        buttonLastPage = new Image(TableWidgetResources.INSTANCE.last());
        buttonLastPage.setStyleName(TableWidgetResources.INSTANCE.css().toolbarButton());
        navigationPanel.add(buttonLastPage);
        buttonLastPage.addClickHandler(new ClickHandler() {
            public void onClick(ClickEvent event) {
                TableWidget.this.buttonLastPageClicked();
            }
        });

        // create, open, delete and copy buttons
        statusLabel = new InlineHTML();
        statusLabel.setStyleName(TableWidgetResources.INSTANCE.css().toolbarButton());
        navigationPanel.add(statusLabel);
        statusLabel.setWordWrap(false);

        buttonCreate = new Image(TableWidgetResources.INSTANCE.create());
        buttonCreate.setStyleName(TableWidgetResources.INSTANCE.css().toolbarButton());
        navigationPanel.add(buttonCreate);
        buttonCreate.addClickHandler(new ClickHandler() {
            public void onClick(ClickEvent event) {
                TableWidget.this.buttonCreateClicked();
            }
        });

        buttonOpen = new Image(TableWidgetResources.INSTANCE.open());
        buttonOpen.setStyleName(TableWidgetResources.INSTANCE.css().toolbarButton());
        navigationPanel.add(buttonOpen);
        buttonOpen.addClickHandler(new ClickHandler() {
            public void onClick(ClickEvent event) {
                TableWidget.this.buttonOpenClicked();
            }
        });

        buttonDelete = new Image(TableWidgetResources.INSTANCE.delete());
        buttonDelete.setStyleName(TableWidgetResources.INSTANCE.css().toolbarButton());
        navigationPanel.add(buttonDelete);
        buttonDelete.addClickHandler(new ClickHandler() {
            public void onClick(ClickEvent event) {
                TableWidget.this.buttonDeleteClicked();
            }
        });

        buttonCopy = new Image(TableWidgetResources.INSTANCE.copy());
        buttonCopy.setStyleName(TableWidgetResources.INSTANCE.css().toolbarButton());
        navigationPanel.add(buttonCopy);
        buttonCopy.addClickHandler(new ClickHandler() {
            public void onClick(ClickEvent event) {
                TableWidget.this.buttonCopyClicked();
            }
        });

        buttonReload = new Image(TableWidgetResources.INSTANCE.reload());
        buttonReload.setStyleName(TableWidgetResources.INSTANCE.css().toolbarButton());
        navigationPanel.add(buttonReload);
        buttonReload.addClickHandler(new ClickHandler() {
            public void onClick(ClickEvent event) {
                TableWidget.this.buttonReloadClicked();
            }
        });

        // search field and button
        InlineHTML strutS = new InlineHTML("&nbsp;");
        strutS.getElement().getStyle().setProperty("marginLeft", "20px");
        navigationPanel.add(strutS);

        searchID = new InlineHTML();
        searchID.setStyleName(TableWidgetResources.INSTANCE.css().toolbarButton());
        searchID.setWordWrap(false);
        searchField = new TextBox();
        searchField.setWidth("200px");
        buttonSearch = new Image(TableWidgetResources.INSTANCE.find());
        buttonSearch.setStyleName(TableWidgetResources.INSTANCE.css().toolbarButton());
        buttonSearch.addClickHandler(new ClickHandler() {
            public void onClick(ClickEvent event) {
                TableWidget.this.buttonSearchClicked();
            }
        });
        adjustSearchLabel();
        navigationPanel.add(searchID);
        navigationPanel.add(searchField);
        navigationPanel.add(buttonSearch);

        InlineHTML strut2 = new InlineHTML("&nbsp;");
        strut2.getElement().getStyle().setProperty("marginLeft", "20px");
        navigationPanel.add(strut2);

        buttonClose = new Image(TableWidgetResources.INSTANCE.cancel());
        buttonClose.setStyleName(TableWidgetResources.INSTANCE.css().toolbarButton());
        buttonClose.addClickHandler(new ClickHandler() {
            public void onClick(ClickEvent event) {
                TableWidget.this.buttonCloseClicked();
            }
        });
        navigationPanel.add(buttonClose);

        buttonSave = new Image(TableWidgetResources.INSTANCE.save());
        buttonSave.setStyleName(TableWidgetResources.INSTANCE.css().toolbarButton());
        buttonSave.addClickHandler(new ClickHandler() {
            public void onClick(ClickEvent event) {
                TableWidget.this.buttonSaveClicked();
            }
        });
        navigationPanel.add(buttonSave);
        navigationPanel.addRight(new Label(""));

        // status text
        showStatus();

        // scrollable grid
        dataPanel = new SimplePanel();
        dataPanel.addStyleName("tabledatapanel");
        ScrollPanel scroller = new ScrollPanel(dataPanel);
        scroller.addStyleName("tablescroller");
        basePanel.add(scroller);
        basePanel.addStyleName("tablebasepanel");
        grid = new FlexTable();

        grid.setCellSpacing(0);

        grid.setWidth("100%");
        grid.setStyleName(TableWidgetResources.INSTANCE.css().tableBody());

        gridFormatter = grid.getFlexCellFormatter();
        grid.getColumnFormatter().setWidth(0, "5px");
        grid.getColumnFormatter().setWidth(1, "10px");
        grid.getColumnFormatter().setWidth(2, "10px");

        // cell and header click handler - sorting and selecting rows
        this.grid.addClickHandler(new ClickHandler() {
            public void onClick(ClickEvent event) {
                TableWidget.this.cellClicked(TableWidget.this.grid.getCellForEvent(event));
            }
        });

        form = new FormWidget(this.view, this, this.ownerForm);
        // form.setWidth("100%");

        // dataPanel.add(grid);
        // dataPanel.add(form);

        resizeGrid();

        switchToGridMode();
        drawHeader();

        navigationPanel.setStyleName(TableWidgetResources.INSTANCE.css().tableNavigationPanel());

    }

    private void resizeGrid() {
        int rows = grid.getRowCount() - 1;
        for (int row = rows; row >= HEADER_ROWS; row--) {
            grid.removeRow(row);
        }
        for (int j = 0; j < view.getProperties().size(); j++) {
            grid.getColumnFormatter().setStyleName(j + LEADING_COLUMNS, TableWidgetResources.INSTANCE.css().tableColumn());
        }
        grid.getColumnFormatter().setStyleName(view.getProperties().size() + LEADING_COLUMNS, TableWidgetResources.INSTANCE.css().tableColumn());
        /*
         * int dataSize = pageData != null ? pageData.size() : 0; if (pageSize
         * <= 0) { grid.resize(dataSize + 1,
         * this.view.getProperties().size()); } else {
         * grid.resize(Math.max(dataSize, pageSize) + 1,
         * this.view.getProperties().size()); }
         */
    }

    private void switchToGridMode() {
        gridMode = true;
        adjustNavigationPanel();
        // dataPanel.clear();
        dataPanel.setWidget(grid);
    }

    private void switchToFormMode() {
        gridMode = false;
        adjustNavigationPanel();
        // dataPanel.clear();
        dataPanel.setWidget(form);
    }

    public void reload() {
        if (view.getQueryParameters() != null && view.getQueryParameters().length > 0) {
            final DialogBox dialogBox = createParamDialogBox();
            dialogBox.setAnimationEnabled(true);
            dialogBox.center();
            // dialogBox.show();
        } else {
            loadData();
        }
    }

    private void adjustSearchLabel() {

        if (this.view.getSortProperty() != null) {
            searchID.setText("Search in " + this.view.getSortProperty().getLocalizedName() + ": ");
            searchID.setVisible(true);
            searchField.setVisible(true);
            buttonSearch.setVisible(true);
        } else {
            searchID.setText("Not sorted");
            searchID.setVisible(false);
            searchField.setVisible(false);
            buttonSearch.setVisible(false);
        }

    }

    private void drawHeader() {
        grid.setWidget(0, 1, getSelectionCheckbox());

        for (int i = 0; i < this.view.getProperties().size(); i++) {
            PropertyDTO<?extends Serializable> prop = this.view.getProperties().get(i);
            if (prop.equals(this.view.getSortProperty())) {
                if (this.view.isSortAscending()) {
                    grid.setWidget(0, i + LEADING_COLUMNS, createSortedColumnHeader(prop.getLocalizedName(), true));
                } else {
                    grid.setWidget(0, i + LEADING_COLUMNS, createSortedColumnHeader(prop.getLocalizedName(), false));
                }
            } else {
                grid.setText(0, i + LEADING_COLUMNS, prop.getLocalizedName());
            }
        }
        grid.getColumnFormatter().setWidth(LEADING_COLUMNS + this.view.getProperties().size(), "5px");
        grid.getRowFormatter().setStyleName(0, TableWidgetResources.INSTANCE.css().tableHeader());
        for (int i = 1; i < this.view.getProperties().size() + LEADING_COLUMNS; i++) {
            grid.getCellFormatter().addStyleName(0, i, TableWidgetResources.INSTANCE.css().tableHeaderCell());
        }
        // insert delimiter row bellow header
        grid.setWidget(1, 0, new InlineHTML(""));
        grid.getCellFormatter().setHeight(1, 0, "4px");
    }

    private Widget createSortedColumnHeader(String caption, boolean ascending) {
        FlowPanel panel = new FlowPanel();
        panel.add(new InlineHTML(caption));
        Image img = null;
        if (ascending) {
            img = new Image(TableWidgetResources.INSTANCE.arrowUp());
        } else {
            img = new Image(TableWidgetResources.INSTANCE.arrowDown());
        }
        img.getElement().getStyle().setProperty("marginLeft", "10px");
        panel.add(img);
        return panel;

    }

    private void loadData() {
        Aplikator.aplikatorService.execute(new GetRecordCount(view, ownerProperty, ownerPrimaryKey, false), new Callback<GetRecordCountResponse>() {
            public void process(GetRecordCountResponse resp) {
                recordCount = resp.getRecordCount();
                showStatus();
            }
        });
        Aplikator.aplikatorService.execute(new GetPage(view, ownerProperty, ownerPrimaryKey, pageOffset, pageSize), new Callback<GetPageResponse>() {
            public void process(GetPageResponse resp) {
                TableWidget.this.pageData = resp.getRecords();
                TableWidget.this.selectedRow = 0;
                redrawPage();
                redrawSelectedRow();
                showStatus();
            }
        });

    }

    private void redrawPage() {
        resizeGrid();
        for (int i = HEADER_ROWS; i < pageData.size() + HEADER_ROWS; i++) {
            grid.setWidget(i, 1, getSelectionCheckbox());
            grid.setWidget(i, 2, getDetailButton(i));
            grid.getColumnFormatter().setStyleName(1, TableWidgetResources.INSTANCE.css().tableColumn());
            grid.getColumnFormatter().setStyleName(2, TableWidgetResources.INSTANCE.css().tableColumn());

            redrawRowContents(i);
        }
        // draw remaining empty rows
        for (int i = pageData.size() + HEADER_ROWS; i < pageSize + HEADER_ROWS; i++) {
            for (int j = 0; j < view.getProperties().size() + 4; j++) {
                grid.setHTML(i, j, EMPTY_CELL);
            }
        }
    }

    private void redrawRowContents(int row) {
        for (int j = 0; j < view.getProperties().size(); j++) {
            Object val = view.getProperties().get(j).getValue(pageData.get(row - HEADER_ROWS));
            grid.setText(row, j + LEADING_COLUMNS, val != null?val.toString():"");
        }
        grid.setHTML(row, view.getProperties().size() + LEADING_COLUMNS, EMPTY_CELL);
    }

    private ToggleButton getDetailButton(final int row) {
        final ToggleButton button = new ToggleButton(new Image(TableWidgetResources.INSTANCE.zoomIn()), new Image(TableWidgetResources.INSTANCE.zoomOut()));
        button.setSize("10px", "14px");
        button.addClickHandler(new ClickHandler() {

            public void onClick(ClickEvent event) {
                if (button.isDown()) {
                    grid.removeCells(row, LEADING_COLUMNS + 1, view.getProperties().size() - 1);
                    gridFormatter.setColSpan(row, LEADING_COLUMNS, view.getProperties().size());

                    Aplikator.aplikatorService.execute(new GetRecord(view, TableWidget.this.pageData.get(row - HEADER_ROWS).getPrimaryKey()), new Callback<GetRecordResponse>() {
                        public void process(GetRecordResponse resp) {
                            Record record = resp.getRecord();
                            grid.setHTML(row, LEADING_COLUMNS, record.toHTML());
                        }
                    });

                } else {
                    gridFormatter.setColSpan(row, LEADING_COLUMNS, 1);
                    redrawRowContents(row);
                }

            }
        });
        return button;
    }

    private CheckBox getSelectionCheckbox() {
        CheckBox checkBox = new CheckBox();

        return checkBox;
    }

    private DialogBox createParamDialogBox() {
        // Create a dialog box and set the caption text

        // Create a table to layout the content
        VerticalPanel dialogContents = new VerticalPanel();
        final DialogBox dialogBox = new DialogBox();
        dialogBox.setText("Input query parameters");
        dialogBox.setWidget(dialogContents);
        dialogContents.setSpacing(4);
        dialogBox.setWidget(dialogContents);
        final int paramCount = view.getQueryParameters().length;
        final TextBox[] paramValues = new TextBox[paramCount];
        for (int i = 0; i < paramCount; i++) {
            HorizontalPanel paramPane = new HorizontalPanel();
            paramPane.add(new Label(view.getQueryParameters()[i].getName()));
            paramValues[i] = new TextBox();

            paramPane.add(paramValues[i]);
            dialogContents.add(paramPane);
        }

        // Add a close button at the bottom of the dialog
        Button closeButton = new Button("OK", new ClickHandler() {
            public void onClick(ClickEvent event) {
                dialogBox.hide();
                StringBuilder title = new StringBuilder();
                for (int i = 0; i < paramCount; i++) {
                    view.getQueryParameters()[i].setValue(paramValues[i].getText());
                    title.append(view.getQueryParameters()[i].getName());
                    title.append(": ");
                    title.append(view.getQueryParameters()[i].getValue());
                    if (i < paramCount - 1) {
                        title.append(", ");
                    }
                }
                if (titleCallback != null) {
                    titleCallback.setTitle(title.toString());
                }
                loadData();
            }
        });
        dialogContents.add(closeButton);
        if (LocaleInfo.getCurrentLocale().isRTL()) {
            dialogContents.setCellHorizontalAlignment(closeButton, HasHorizontalAlignment.ALIGN_LEFT);

        } else {
            dialogContents.setCellHorizontalAlignment(closeButton, HasHorizontalAlignment.ALIGN_RIGHT);
        }

        // Return the dialog box
        return dialogBox;
    }

    private void cellClicked(Cell cell) {
        if (cell == null)
            return;
        if (cell.getRowIndex() == 0) {// TODO implement sorting allowed only for
            // columns specified in the view
            /*
             * if ((column == 0) && (this.allowRowMark)) { // Sorting by the
             * "mark" column is not allowed return; }
             */
            int column = cell.getCellIndex();
            PropertyDTO<?extends Serializable> sp = this.view.getProperties().get(column - 3);
            pageOffset = 0;
            this.applySorting(sp);
        } else if (cell.getRowIndex() == 1) {// do nothing for the delimiter row
        } else {
            long currentTime = System.currentTimeMillis();

            if ((cell.getRowIndex()-HEADER_ROWS) < this.pageData.size() ) {
                this.selectedRow = cell.getRowIndex()-HEADER_ROWS;
            }
            if ((currentTime - lastClickTime < DOUBLECLICK_TRESHOLD) && this.selectedRow == lastClickRow) {// doubleclick
                                                                                                           // detected
                lastClickTime = 0;
                lastClickRow = 0;
                buttonOpenClicked();
            } else {
                lastClickTime = currentTime;
                lastClickRow = this.selectedRow;
            }
        }
        redrawSelectedRow();
    }

    private void applySorting(PropertyDTO<?extends Serializable> column) {
        if (column.equals(this.view.getSortProperty())) {
            applySorting(this.view.getSortProperty(), !this.view.isSortAscending());
        } else {
            applySorting(column, true);
        }
    }

    public void applySorting(PropertyDTO<?extends Serializable> sortProperty, boolean ascending) {
        this.view.setSortProperty(sortProperty);
        this.view.setSortAscending(ascending);
        adjustSearchLabel();
        drawHeader();
        loadData();
    }

    private void redrawSelectedRow() {
        RowFormatter gridRowFormatter = grid.getRowFormatter();
        for (int row = HEADER_ROWS; row < this.pageData.size() + HEADER_ROWS; row++) {
            if (row == this.selectedRow+HEADER_ROWS) {
                gridRowFormatter.setStyleName(row, TableWidgetResources.INSTANCE.css().tableSelectedRow());
            } else if (row % 2 == 0) {
                gridRowFormatter.setStyleName(row, TableWidgetResources.INSTANCE.css().tableEvenRow());
            } else {
                gridRowFormatter.setStyleName(row, TableWidgetResources.INSTANCE.css().tableOddRow());
            }
        }
    }

    public PrimaryKey getSelectedPrimaryKey() {
        return getSelectedRecord().getPrimaryKey();
    }

    public Record getSelectedRecord() {
        return this.pageData.get(this.selectedRow);
    }

    private void buttonLastPageClicked() {
        if (gridMode) {
            if (pageSize > 0) {
                pageOffset = recordCount - pageSize;
                loadData();
            }
        } else {
            closeForm(new Command() {
                public void execute() {
                    if (pageSize > 0) {
                        pageOffset = recordCount - pageSize;
                        loadData();
                    }
                    selectedRow = pageData.size();
                    openForm();

                }
            });

        }
    }

    private void buttonNextPageClicked() {
        if (gridMode) {
            if (pageSize > 0) {
                pageOffset = Math.min(recordCount - 1, pageOffset + pageSize);
                loadData();
            }
        } else {
            if (selectedRow < pageData.size()) {
                closeForm(new Command() {
                    public void execute() {
                        selectedRow++;
                        openForm();

                    }
                });

            } else {
                if (pageSize > 0) {
                    closeForm(new Command() {
                        public void execute() {
                            pageOffset = Math.min(recordCount - 1, pageOffset + pageSize);
                            loadData();
                            selectedRow = 0;
                            openForm();

                        }
                    });

                }
            }
        }
    }

    private void buttonPrevPageClicked() {
        if (gridMode) {
            if (pageSize > 0) {
                pageOffset = Math.max(0, pageOffset - pageSize);
                loadData();
            }
        } else {
            if (selectedRow > 1) {
                closeForm(new Command() {
                    public void execute() {
                        selectedRow--;
                        openForm();

                    }
                });

            } else {
                if (pageSize > 0) {
                    closeForm(new Command() {
                        public void execute() {
                            pageOffset = Math.max(0, pageOffset - pageSize);
                            loadData();
                            selectedRow = pageData.size();
                            openForm();

                        }
                    });

                }
            }
        }
    }

    private void buttonFirstPageClicked() {
        if (gridMode) {
            if (pageSize > 0) {
                pageOffset = 0;
                loadData();
            }
        } else {
            closeForm(new Command() {
                public void execute() {
                    if (pageSize > 0) {
                        pageOffset = 0;
                        loadData();
                    }
                    selectedRow = 0;
                    openForm();

                }
            });

        }
    }

    private void buttonSearchClicked() {// TODO add support for pageSize <-1

        view.setSearchString(searchField.getText());
        search();

    }

    public void search() {
        if (view.getSearchString() != null && !"".equals(view.getSearchString())) {
            Aplikator.aplikatorService.execute(new GetRecordCount(view, ownerProperty, ownerPrimaryKey, true), new Callback<GetRecordCountResponse>() {
                public void process(GetRecordCountResponse resp) {
                    pageOffset = resp.getRecordCount();
                    loadData();
                }
            });
        } else {
            loadData();
        }
    }

    private void showStatus() {
        String text = "";
        if (pageSize > 0) {
            text = "   Records: " + (pageOffset + 1) + " - " + (Math.min(recordCount, pageOffset + pageSize)) + " of " + recordCount + "   ";
        } else {
            text = "   Records: " + recordCount + "   ";
        }
        statusLabel.setText(text);
    }

    private void buttonCreateClicked() {
        // Form form = openForm();
        switchToFormMode();
        if (ownerProperty != null) {
            form.addRecord(recordContainer, ownerProperty, ownerPrimaryKey, null);
        } else {
            form.addRecord(new RecordContainer(), null, null, null);
        }
    }

    private void buttonOpenClicked() {
        switchToFormMode();
        openForm();
    }

    private void buttonCloseClicked() {
        closeForm(new Command() {
            public void execute() {
                switchToGridMode();

            }
        });

    }

    private void closeForm(Command afterConfirmation) {
        form.onClose(afterConfirmation);
    }

    private void openForm() {
        if (ownerProperty != null) {
            form.displayRecord(getSelectedPrimaryKey(), recordContainer);
        } else {
            form.displayRecord(getSelectedPrimaryKey(), new RecordContainer());
        }
    }

    private void buttonSaveClicked() {
        form.save();
        switchToGridMode();
    }

    public void save() {
        if (form != null) {
            form.save();
        }
    }

    private void buttonDeleteClicked() {
        if (ownerProperty != null) {
            recordContainer.addRecord(view, getSelectedRecord(), null, Operation.DELETE);
            pageData.remove(TableWidget.this.selectedRow);
            redrawPage();
        } else {
            RecordContainer newContainer = new RecordContainer();
            newContainer.addRecord(view, getSelectedRecord(), null, Operation.DELETE);
            Aplikator.aplikatorService.execute(new ProcessRecords(newContainer), new Callback<ProcessRecordsResponse>() {
                public void process(ProcessRecordsResponse records) {
                    pageData.remove(TableWidget.this.selectedRow);
                    redrawPage();
                }
            });
        }
    }

    private void buttonCopyClicked() {
        switchToFormMode();
        if (ownerProperty != null) {
            form.addRecord(recordContainer, ownerProperty, ownerPrimaryKey, getSelectedRecord());
        } else {
            form.addRecord(new RecordContainer(), null, null, getSelectedRecord());
        }
    }

    private void buttonReloadClicked() {
        reload();
    }

    public void addRecord(Record record) {
        pageData.add(record);
        redrawPage();
    }

    public void updateRecord(Record record) {
        for (int i = 0; i < pageData.size(); i++) {
            Record rec = pageData.get(i);
            if (rec.getPrimaryKey().equals(record.getPrimaryKey())) {
                pageData.set(i, record);
                break;
            }
        }
        redrawPage();
    }

    public PrimaryKey getOwnerPrimaryKey() {
        return ownerPrimaryKey;
    }

    public void setOwnerPrimaryKey(PrimaryKey value) {
        ownerPrimaryKey = value;
        reload();
    }

    public void setRecordContainer(RecordContainer recordContainer) {
        this.recordContainer = recordContainer;
    }

    private void adjustNavigationPanel() {
        buttonOpen.setVisible(gridMode);
        buttonReload.setVisible(gridMode);
        buttonClose.setVisible(!gridMode);
        buttonSave.setVisible(!gridMode && (ownerForm == null));
        statusLabel.setVisible(gridMode);

    }

    public void setTitleCallback(MainPanelTitleCallback titleCallback) {
        this.titleCallback = titleCallback;
    }

    public void setDirty(boolean dirty) {
        // for (Form nestedForm:nestedForms){
        // nestedForm.setDirty(dirty);
        // }
    }
}
